package com.forest.oss.impl.tencent;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.model.*;
import com.qcloud.cos.region.Region;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import com.forest.oss.constants.AclType;
import com.forest.oss.impl.OssProperties;
import com.forest.oss.AbstractOssClient;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.stream.Collectors;


public class TencentOssClient extends AbstractOssClient {

    private static final Logger log = LoggerFactory.getLogger(TencentOssClient.class);

    private TencentOssProperties tencentOssProperties;

    private COSClient client;

    public TencentOssClient(TencentOssProperties tencentOssProperties) {
        System.out.println("--------------加载腾讯云对象存储------------");
        this.tencentOssProperties = tencentOssProperties;
        client = getOssClient();
    }

    private COSClient getOssClient() {
        // 1 初始化用户身份信息(appid, secretId, secretKey)
        COSCredentials cred = new BasicCOSCredentials(tencentOssProperties.getAppKeyId(), tencentOssProperties.getAppSecret());
        // 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
        ClientConfig clientConfig = new ClientConfig(new Region("ap-chongqing"));
        return new COSClient(cred, clientConfig);
    }

    @Override
    public OssProperties getProperties() {
        return this.tencentOssProperties;
    }

    @Override
    public String getFolder() {
        return super.getFolder(tencentOssProperties.getProject());
    }

    @Override
    public String upload(String key, String folder, InputStream inputStream, AclType acl) {
        // 上传同时设置访问权限
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType(getContentType(key));
        try {
            metadata.setContentLength(inputStream.available());
        } catch (IOException e) {
            log.error("获取文件流有限内容长度异常：{}", e.getMessage(), e);
        }

        PutObjectRequest request = new PutObjectRequest(tencentOssProperties.getBucket(), folder + key, inputStream, metadata);
        request.setCannedAcl(CannedAccessControlList.valueOf(acl.name()));
        client.putObject(request);
        return folder + key;
    }

    @Override
    public InputStream download(String key) {
        COSObject object = client.getObject(tencentOssProperties.getBucket(), key);
        COSObjectInputStream objectContent = object.getObjectContent();
        byte [] content = IoUtil.readBytes(objectContent);
        return new ByteArrayInputStream(content);
    }

    @Override
    public String getFile(String key, AclType acl) {
        if(StrUtil.equalsIgnoreCase(CannedAccessControlList.PublicRead.name(), acl.name())) {
            return buildPublicUrl(tencentOssProperties.getBucketDomain(), key);
        } else {
            String url = client.getObjectUrl(tencentOssProperties.getBucket(), key).getPath();
            return url;
        }
    }

    @Override
    public void delete(String key) {
        client.deleteObject(tencentOssProperties.getBucket(), key);
    }

    @Override
    public List<String> batchDelete(List<String> keys, boolean quiet) {
        Assert.isTrue(CollectionUtils.isEmpty(keys), "删除的文件keys不能为空");
        Assert.isTrue(keys.size() > 1000, "删除的文件keys超过了最大限制1000个");
        DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(tencentOssProperties.getBucket())
                .withKeys(keys.stream().map(k -> new DeleteObjectsRequest.KeyVersion(k)).collect(Collectors.toList()))
                .withQuiet(quiet);
        DeleteObjectsResult result = client.deleteObjects(deleteObjectsRequest);
        List<String> res = result.getDeletedObjects().stream().map(DeleteObjectsResult.DeletedObject::getKey).collect(Collectors.toList());
        return res;
    }

    @Override
    public Boolean exists(String key) {
        return client.doesObjectExist(tencentOssProperties.getBucket(), key);
    }
}
